package com.gxitsky.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.springframework.util.ObjectUtils;

import javax.xml.namespace.QName;
import javax.xml.soap.*;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author gxing
 * @desc WebService工具类
 * @date 2022/4/11
 */
@Slf4j
public class WebServiceUtil {

    /**
     * @param url         服务地址
     * @param nameSpace   命称空间
     * @param operation   操作名
     * @param prefix      前缀
     * @param isQualified 是否全限定
     * @param paramMap    参数Map
     * @desc Web Service Soap请求
     * @author gxing
     * @date 2022/6/6 14:30
     */
    public static String soapRequest(String url, String nameSpace, String operation, String prefix, boolean isQualified, Map<String, String> paramMap) throws IOException, SOAPException {
        ByteArrayOutputStream outputStream = null;
        try {
            SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = factory.createConnection();
            MessageFactory messageFactory = MessageFactory.newInstance();
            //消息体
            SOAPMessage message = messageFactory.createMessage();
            SOAPPart part = message.getSOAPPart();
            SOAPEnvelope envelope = part.getEnvelope();
            envelope.addNamespaceDeclaration(prefix, nameSpace);

            SOAPHeader header = message.getSOAPHeader();

            header.detachNode();
            SOAPBody body = message.getSOAPBody();

            QName bodyName = new QName(nameSpace, operation, prefix);
            SOAPBodyElement element = body.addBodyElement(bodyName);

            // 组装请求参数
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                QName sub = null;
                if (isQualified) {
                    sub = new QName(nameSpace, entry.getKey(), prefix);
                } else {
                    sub = new QName(entry.getKey());
                }
                SOAPElement childElement = element.addChildElement(sub);
                childElement.addTextNode(entry.getValue());
            }

            //请求体
            outputStream = new ByteArrayOutputStream();
            message.writeTo(outputStream);
            String requestBody = outputStream.toString(Charset.defaultCharset());
            //执行请求
            log.info("Web Service Request:{}", requestBody);
            SOAPMessage result = connection.call(message, url);
            log.info("Web Service Request End.");

            //响应体
            outputStream.reset();
            result.writeTo(outputStream);
            String responseBody = outputStream.toString(Charset.defaultCharset());
            log.info("Web Service Response:{}", responseBody);

            //响应文本
            org.w3c.dom.Node firstChild = result.getSOAPBody().getFirstChild();
            org.w3c.dom.Node subChild = firstChild.getFirstChild();
            return subChild.getTextContent();
        } catch (Exception e) {
            throw e;
        } finally {
            if (!ObjectUtils.isEmpty(outputStream)) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
